import SwiftUI
import AppIntents
import CalendarShared

public struct WeekView: View {
    public var entry: MediumEntry
    public var todyIntent: (any AppIntent)?
    public var lastIntent: (any AppIntent)?
    public var nextIntent: (any AppIntent)?
    @Environment(\.widgetRenderingMode) var renderingMode
    @Environment(\.colorScheme) var colorScheme

    public init(entry: MediumEntry, todyIntent: (any AppIntent)?, lastIntent: (any AppIntent)?, nextIntent: (any AppIntent)?) {
        self.entry = entry
        self.todyIntent = todyIntent
        self.lastIntent = lastIntent
        self.nextIntent = nextIntent
    }

    public var body: some View {
        GeometryReader { geometry in
            VStack(spacing: 0) {
                header
                weekView(geometry)
                dateView(geometry)
            }
        }
    }
}

private extension WeekView {
    struct Constants {
        static let headerHeight: CGFloat = 44
        static let weekHeight: CGFloat = 26
    }

    var header: some View {
        let month = NSLocalizedString("BearCalendar.calendar.month", bundle: moduleBundle, comment: "")
        let format = entry.language.isEnglish ? "MMM yyyy" : "M\(month) yyyy"
        let title = entry.date.formated(.other(format), language: entry.language)
        return HStack(spacing: 10) {
            Spacer()
            #if os(iOS)
            if #available(iOS 17.0, *) {
                IntentButton(intent: lastIntent) {
                    Image(systemName: "chevron.left")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 13, height: 13)
                        .foreground(color: entry.normal.color(colorScheme))
                }
                IntentButton(intent: todyIntent) {
                    Text(title)
                        .font(.title2)
                        .foreground(color:entry.normal.color(colorScheme))
                        .widgetAccentable(renderingMode == .accented)
                }
                IntentButton(intent: nextIntent) {
                    Image(systemName: "chevron.right")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 13, height: 13)
                        .foreground(color: entry.normal.color(colorScheme))
                }
            } else {
                Text(title)
                    .font(.title2)
                    .foreground(color: entry.normal.color(colorScheme))
                    .widgetAccentable(renderingMode == .accented)
            }
            #else
            if #available(macOS 14.0, *) {
                IntentButton(intent: lastIntent) {
                    Image(systemName: "chevron.left")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 13, height: 13)
                        .foreground(color: entry.normal.color(colorScheme))
                }
                IntentButton(intent: todyIntent) {
                    Text(title)
                        .font(.title2)
                        .foreground(color:entry.normal.color(colorScheme))
                        .widgetAccentable(renderingMode == .accented)
                }
                IntentButton(intent: nextIntent) {
                    Image(systemName: "chevron.right")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 13, height: 13)
                        .foreground(color: entry.normal.color(colorScheme))
                }
            } else {
                Text(title)
                    .font(.title2)
                    .foreground(color: entry.normal.color(colorScheme))
                    .widgetAccentable(renderingMode == .accented)
            }
            #endif
            Spacer()
        }
        .frame(height: Constants.headerHeight, alignment: .center)
        .padding(.horizontal, 15)
    }

    func weekView(_ geometry: GeometryProxy) -> some View {
        LazyVGrid(columns: Array(repeating: GridItem(spacing: 5), count: 7), spacing: 5) {
            let itemW = (geometry.size.width - 40) / 7
            let itemH = Constants.weekHeight
            ForEach(Week.weeks(beginAt: entry.firstWeek), id: \.self) { week in
                Button {} label: {
                    Text(week.title(entry.language))
                        .font(.body)
                        .foreground(color: weekColor(week))
                        .widgetAccentable(renderingMode == .accented)
                }
                .buttonStyle(.plain)
                .frame(width: itemW, height: itemH, alignment: .center)
            }
        }.padding(.horizontal, 5)
    }

    func dateView(_ geometry: GeometryProxy) -> some View {
        LazyVGrid(columns: Array(repeating: GridItem(spacing: 5), count: 7), spacing: 5) {
            let row = entry.days.count / 7
            let itemW = (geometry.size.width - 40) / 7
            let spacing = (row + 1) * 5
            let itemH = (geometry.size.height - Constants.headerHeight - Constants.weekHeight - CGFloat(spacing)) / CGFloat(row)
            ForEach(entry.days, id: \.id) { entity in
                Button {} label: {
                    VStack(spacing: 0) {
                        HStack(spacing: 4) {
                            Text("\(entity.date.day)")
                                .font(.system(size: 14).bold())
                                .foreground(color: dateColor(entity))
                                .widgetAccentable(renderingMode == .accented)
                            if entity.tiaoxiu != .none, entry.showFestival {
                                Image(entity.tiaoxiu == .work ? "work" : "rest")
                                    .resizable()
                                    .frame(width: 10, height: 11)
                                    .foreground(color: workColor(entity))
                            }
                        }
                        .padding(.top, 3)
                        if entry.showLunar {
                            Text(entity.lunar)
                                .font(.system(size: 10))
                                .foreground(color: festivalColor(entity))
                                .widgetAccentable(renderingMode == .accented)
                                .padding(.bottom, 3)
                        }
                        eventView(entity)
                    }
                }
                .buttonStyle(.plain)
                .frame(width: itemW, height: itemH, alignment: .center)
                .background(RoundedRectangle(cornerRadius: 8).stroke(entity.date.isCurrentDay ? entry.current.color(colorScheme) : .clear))
            }
        }.padding(.all, 5)
    }

    @ViewBuilder
    func eventView(_ model: DayModel) -> some View {
        if entry.showEvent, model.events.count > 0, entry.showReminder, model.reminders.count > 0 {
            HStack(spacing: 2) {
                entry.calendar.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1).cornerRadius(2).frame(width: 4, height: 4)
                entry.reminder.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1).cornerRadius(2).frame(width: 4, height: 4)
            }
        } else if entry.showEvent, model.events.count > 0 {
            entry.calendar.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1).cornerRadius(2).frame(width: 4, height: 4)
        } else if entry.showReminder, model.reminders.count > 0 {
            entry.reminder.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1).cornerRadius(2).frame(width: 4, height: 4)
        } else {
            EmptyView()
        }
    }

    func dateColor(_ model: DayModel) -> Color {
        // 周末
        if model.date.isWeekDay {
            return entry.week.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1)
        }
        // 一般日期
        return entry.normal.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1)
    }

    func festivalColor(_ model: DayModel) -> Color {
        // 节假日
        if model.isFestival {
            return entry.festival.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1)
        }
        // 周末
        if model.date.isWeekDay {
            return entry.week.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1)
        }
        // 一般日期
        return entry.normal.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1)
    }

    func workColor(_ model: DayModel) -> Color {
        switch model.tiaoxiu {
        case .work: entry.work.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1)
        case .rest: entry.rest.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1)
        case .none: entry.normal.color(colorScheme).opacity(model.mode != .current ? 0.3 : 1)
        }
    }

    func weekColor(_ week: Week) -> Color {
        if week == .sun || week == .sat {
            entry.week.color(colorScheme)
        } else {
            entry.normal.color(colorScheme)
        }
    }
}
